<#-- HTTP客户端模板 - 基于HttpMetaData生成 -->
package com.generated.${packageName};

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.Objects;
<#if needsJson>
    import com.fasterxml.jackson.databind.ObjectMapper;
    import java.util.HashMap;
    import java.util.Map;
</#if>

/**
* ${apiName} HTTP客户端
* <#if description?? && description.mark??>
    * 描述: ${description.mark}
    * </#if>
* 生成时间: ${.now?string("yyyy-MM-dd HH:mm:ss")}
* 端点: ${httpMethod} http://${host}:${port}${route}
*/
public class ${apiName}Client {

private final String baseUrl;
private final HttpClient httpClient;
<#if needsJson>
    private final ObjectMapper objectMapper;
</#if>

// 默认配置
private static final int DEFAULT_TIMEOUT = 10000;
private static final String USER_AGENT = "${apiName}Client/1.0";

/**
* 使用默认配置创建客户端
*/
public ${apiName}Client() {
this("http://${host}:${port}");
}

/**
* 自定义基础URL创建客户端
*/
public ${apiName}Client(String baseUrl) {
this(baseUrl, DEFAULT_TIMEOUT);
}

/**
* 完整配置创建客户端
*/
public ${apiName}Client(String baseUrl, int timeoutMs) {
this.baseUrl = normalizeBaseUrl(baseUrl);
this.httpClient = HttpClient.newBuilder()
.connectTimeout(Duration.ofMillis(timeoutMs))
.version(HttpClient.Version.HTTP_1_1)
.build();
<#if needsJson>
    this.objectMapper = new ObjectMapper();
</#if>
}

/**
* 执行${apiName}操作
<#list enterParameters as param>
    * @param ${param.name} <#if param.description?? && param.description.mark??>${param.description.mark}<#else>${param.name}参数</#if><#if param.required> (必填)</#if>
</#list>
* @return 操作结果
* @throws RuntimeException 当请求失败或参数校验不通过时抛出
*/
public ${apiName}Response execute(<#list enterParameters as param>
${getJavaType(param.type)} ${param.name}<#if param_has_next>, </#if>
</#list>) {

// 参数校验
validateParameters(<#list enterParameters as param>${param.name}<#if param_has_next>, </#if></#list>);

try {
// 构建请求
HttpRequest request = buildHttpRequest(<#list enterParameters as param>${param.name}<#if param_has_next>, </#if></#list>);

// 发送请求
HttpResponse<String> response = httpClient.send(
    request,
    HttpResponse.BodyHandlers.ofString()
    );

    // 处理响应
    return processResponse(response);

    } catch (Exception e) {
    throw new RuntimeException("${apiName}请求执行失败: " + e.getMessage(), e);
    }
    }

    /**
    * 异步执行${apiName}操作
    */
    public java.util.concurrent.CompletableFuture<${apiName}Response> executeAsync(<#list enterParameters as param>
        ${getJavaType(param.type)} ${param.name}<#if param_has_next>, </#if>
        </#list>) {

        validateParameters(<#list enterParameters as param>${param.name}<#if param_has_next>, </#if></#list>);

        try {
        HttpRequest request = buildHttpRequest(<#list enterParameters as param>${param.name}<#if param_has_next>, </#if></#list>);

        return httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString())
        .thenApply(this::processResponse)
        .exceptionally(e -> {
        throw new RuntimeException("${apiName}异步请求失败: " + e.getMessage(), e);
        });

        } catch (Exception e) {
        return java.util.concurrent.CompletableFuture.failedFuture(
        new RuntimeException("${apiName}异步请求构建失败: " + e.getMessage(), e)
        );
        }
        }

        /**
        * 参数校验
        */
        private void validateParameters(<#list enterParameters as param>${getJavaType(param.type)} ${param.name}<#if param_has_next>, </#if></#list>) {
        <#list enterParameters as param>
            <#if param.required>
                // 校验必填参数: ${param.name}
                if (${param.name} == null) {
                throw new IllegalArgumentException("参数'${param.name}'不能为空");
                }
            </#if>

            <#if param.description??>
                <#if param.description.min??>
                    <#if param.type == "STRING">
                        if (${param.name} != null && ${param.name}.length() < ${param.description.min}) {
                        throw new IllegalArgumentException("参数'${param.name}'长度不能小于${param.description.min}");
                        }
                    <#elseif param.type == "NUMBER">
                        if (${param.name} != null && ${param.name} < ${param.description.min}) {
                        throw new IllegalArgumentException("参数'${param.name}'值不能小于${param.description.min}");
                        }
                    </#if>
                </#if>

                <#if param.description.max??>
                    <#if param.type == "STRING">
                        if (${param.name} != null && ${param.name}.length() > ${param.description.max}) {
                        throw new IllegalArgumentException("参数'${param.name}'长度不能大于${param.description.max}");
                        }
                    <#elseif param.type == "NUMBER">
                        if (${param.name} != null && ${param.name} > ${param.description.max}) {
                        throw new IllegalArgumentException("参数'${param.name}'值不能大于${param.description.max}");
                        }
                    </#if>
                </#if>

                <#if param.description.pattern?? && param.type == "STRING">
                    if (${param.name} != null && !${param.name}.matches("${param.description.pattern}")) {
                    throw new IllegalArgumentException("参数'${param.name}'格式不符合要求");
                    }
                </#if>
            </#if>
        </#list>
        }

        /**
        * 构建HTTP请求
        */
        private HttpRequest buildHttpRequest(<#list enterParameters as param>${getJavaType(param.type)} ${param.name}<#if param_has_next>, </#if></#list>) {
        HttpRequest.Builder builder = HttpRequest.newBuilder()
        .uri(buildRequestUri(<#list enterParameters as param>${param.name}<#if param_has_next>, </#if></#list>))
        .timeout(Duration.ofMillis(DEFAULT_TIMEOUT))
        .header("User-Agent", USER_AGENT)
        .header("Accept", "application/json");

        <#if httpMethod == "GET">
            builder.GET();
        <#elseif httpMethod == "POST">
            builder.POST(buildRequestBody(<#list enterParameters as param>${param.name}<#if param_has_next>, </#if></#list>))
            .header("Content-Type", "application/json");
        <#elseif httpMethod == "PUT">
            builder.PUT(buildRequestBody(<#list enterParameters as param>${param.name}<#if param_has_next>, </#if></#list>))
            .header("Content-Type", "application/json");
        <#elseif httpMethod == "DELETE">
            builder.DELETE();
        <#else>
            builder.method("${httpMethod}", buildRequestBody(<#list enterParameters as param>${param.name}<#if param_has_next>, </#if></#list>));
        </#if>

        return builder.build();
        }

        /**
        * 构建请求URI
        */
        private URI buildRequestUri(<#list enterParameters as param>${getJavaType(param.type)} ${param.name}<#if param_has_next>, </#if></#list>) {
        String url = baseUrl + "${route}";

        <#if httpMethod == "GET" && enterParameters?has_content>
            // 为GET请求构建查询字符串
            String queryString = buildQueryString(<#list enterParameters as param>${param.name}<#if param_has_next>, </#if></#list>);
            if (!queryString.isEmpty()) {
            url += "?" + queryString;
            }
        </#if>

        return URI.create(url);
        }

        <#if httpMethod == "GET" && enterParameters?has_content>
            /**
            * 构建查询字符串（GET请求专用）
            */
            private String buildQueryString(<#list enterParameters as param>${getJavaType(param.type)} ${param.name}<#if param_has_next>, </#if></#list>) {
            StringBuilder query = new StringBuilder();
            <#list enterParameters as param>
                <#if param.type == "STRING" || param.type == "NUMBER" || param.type == "BOOLEAN">
                    if (${param.name} != null) {
                    if (query.length() > 0) {
                    query.append("&");
                    }
                    query.append("${param.name}=");
                    <#if param.type == "STRING">
                        query.append(java.net.URLEncoder.encode(${param.name}, java.nio.charset.StandardCharsets.UTF_8));
                    <#else>
                        query.append(String.valueOf(${param.name}));
                    </#if>
                    }
                </#if>
            </#list>
            return query.toString();
            }
        </#if>

        <#if httpMethod != "GET">
            /**
            * 构建请求体（非GET请求专用）
            */
            private HttpRequest.BodyPublisher buildRequestBody(<#list enterParameters as param>${getJavaType(param.type)} ${param.name}<#if param_has_next>, </#if></#list>) {
            <#if needsJson>
                try {
                Map<String, Object> requestBody = new HashMap<>();
                <#list enterParameters as param>
                    <#if param.type != "FILE"> <#-- 排除文件类型，需要特殊处理 -->
                        requestBody.put("${param.name}", ${param.name});
                    </#if>
                </#list>
                String jsonBody = objectMapper.writeValueAsString(requestBody);
                return HttpRequest.BodyPublishers.ofString(jsonBody);
                } catch (Exception e) {
                throw new RuntimeException("构建请求体失败: " + e.getMessage(), e);
                }
            <#else>
                return HttpRequest.BodyPublishers.noBody();
            </#if>
            }
        </#if>

        /**
        * 处理HTTP响应
        */
        private ${apiName}Response processResponse(HttpResponse<String> httpResponse) {
            ${apiName}Response response = new ${apiName}Response();
            response.setStatusCode(httpResponse.statusCode());
            response.setHeaders(httpResponse.headers().map());
            response.setBody(httpResponse.body());

            <#if exitParameters?has_content>
                // 解析响应数据
                parseResponseBody(httpResponse, response);
            </#if>

            return response;
            }

            <#if exitParameters?has_content>
            /**
            * 解析响应体到具体字段
            */
            private void parseResponseBody(HttpResponse<String> httpResponse, ${apiName}Response response) {
                if (httpResponse.statusCode() == 200 && httpResponse.body() != null && !httpResponse.body().trim().isEmpty()) {
                try {
                <#if needsJson>
                    Map<String, Object> responseMap = objectMapper.readValue(
                              httpResponse.body(),
                              new com.fasterxml.jackson.core.type.TypeReference<Map<String, Object>>() {}
                    );

                    <#list exitParameters as param>
                        if (responseMap.containsKey("${param.name}")) {
                        Object value = responseMap.get("${param.name}");
                        <#if param.type == "STRING">
                            response.set${param.name?cap_first}(value != null ? value.toString() : null);
                        <#elseif param.type == "NUMBER">
                            if (value instanceof Number) {
                            response.set${param.name?cap_first}(((${getJavaType(param.type)}) value));
                            } else if (value != null) {
                            response.set${param.name?cap_first}(${getJavaType(param.type)}.valueOf(value.toString()));
                            }
                        <#elseif param.type == "BOOLEAN">
                            if (value instanceof Boolean) {
                            response.set${param.name?cap_first}((Boolean) value);
                            } else if (value != null) {
                            response.set${param.name?cap_first}(Boolean.parseBoolean(value.toString()));
                            }
                        <#else>
                            response.set${param.name?cap_first}(value);
                        </#if>
                        }
                    </#list>
                </#if>
                } catch (Exception e) {
                // JSON解析失败，记录日志但继续返回原始响应
                System.err.println("${apiName}响应解析失败: " + e.getMessage());
                }
                }
                }
                </#if>

                /**
                * 规范化基础URL
                */
                private String normalizeBaseUrl(String url) {
                if (url == null || url.trim().isEmpty()) {
                return "http://${host}:${port}";
                }
                url = url.trim();
                if (url.endsWith("/")) {
                url = url.substring(0, url.length() - 1);
                }
                return url;
                }

                /**
                * 获取客户端状态信息
                */
                public String getClientInfo() {
                return "${apiName}Client [baseUrl=" + baseUrl + ", timeout=" + DEFAULT_TIMEOUT + "ms]";
                }
                }